<!DOCTYPE html>
<html>
<head>
<title>Absolute positioning within the viewport</title>
<meta name="description" content="A diagram that does not scroll or zoom and has a fixed area in which to move parts." />
<!-- Copyright 1998-2016 by Northwoods Software Corporation. -->
<meta charset="UTF-8">
<script src="go.js"></script>
<link href="../assets/css/goSamples.css" rel="stylesheet" type="text/css" />  <!-- you don't need to use this -->
<script src="goSamples.js"></script>  <!-- this is only for the GoJS Samples framework -->
<script id="code">
  function init() {
    if (window.goSamples) goSamples();  // init for these samples -- you don't need to call this
    var $ = go.GraphObject.make;

    myDiagram =
      $(go.Diagram, "myDiagramDiv",
        {
          fixedBounds: new go.Rect(0, 0, 500, 300),  // document is always 500x300 units
          allowHorizontalScroll: false,  // disallow scrolling or panning
          allowVerticalScroll: false,
          allowZoom: false,              // disallow zooming
          "animationManager.isEnabled": false,
          "undoManager.isEnabled": true,
          "ModelChanged": function(e) {     // just for demonstration purposes,
            if (e.isTransactionFinished) {  // show the model data in the page's TextArea
              document.getElementById("mySavedModel").textContent = e.model.toJson();
            }
        }
      });

    // the light-yellow background Part showing the fixed bounds of the diagram contents
    myDiagram.add(
      $(go.Part,
        { layerName: "Grid", position: myDiagram.fixedBounds.position },
        $(go.Shape, { fill: "lightyellow", strokeWidth: 0, desiredSize: myDiagram.fixedBounds.size })
      ));

    // this function is the Node.dragComputation, to limit the movement of the parts
    function stayInFixedArea(part, pt, gridpt) {
      var diagram = part.diagram;
      if (diagram === null) return pt;
      // compute the document area without padding
      var v = diagram.documentBounds.copy();
      v.subtractMargin(diagram.padding);
      // get the bounds of the part being dragged
      var b = part.actualBounds;
      var loc = part.location;
      // now limit the location appropriately
      var x = Math.max(v.x, Math.min(pt.x, v.right - b.width)) + (loc.x - b.x);
      var y = Math.max(v.y, Math.min(pt.y, v.bottom - b.height)) + (loc.y - b.y);
      return new go.Point(x, y);
    }

    myDiagram.nodeTemplate =
      $(go.Part, "Auto",  // Part instead of Node, assuming no Links!
        { dragComputation: stayInFixedArea },
        // get the size from the model data
        new go.Binding("desiredSize", "size", go.Size.parse),
        // get and set the position in the model data
        new go.Binding("position", "pos", go.Point.parse).makeTwoWay(go.Point.stringify),
        // temporarily put selected nodes in Foreground layer
        new go.Binding("layerName", "isSelected", function(s) { return s ? "Foreground" : ""; }).ofObject(),
        $(go.Shape, "Rectangle",
          { strokeWidth: 0 },  // avoid extra thickness from the stroke
          new go.Binding("fill", "color")),
        $(go.TextBlock,
          new go.Binding("text", "color"))
      );

    myDiagram.model = new go.GraphLinksModel([
      { pos: "0 0", size: "50 50", color: go.Brush.randomColor() },
      { pos: "120 20", size: "100 100", color: go.Brush.randomColor() },
      { pos: "100 200", size: "100 50", color: go.Brush.randomColor() },
      { pos: "200 50", size: "50 100", color: go.Brush.randomColor() }
    ]);
  }
</script>
</head>
<body onload="init()">
  <div id="sample">
    <p>Absolute positioning within the viewport, with no scrolling (or panning) or zooming allowed.</p>
    <div id="myDiagramDiv" style="border: solid 1px black; width:100%; height:400px"></div>
    <p>
      There is a special lightyellow background Part that shows the fixed area where Parts may be.
      It is in the "Grid" Layer so that it is not selectable and is always behind the regular Parts.
    </p>
    <p>
      Parts may not be dragged outside of the fixed document area of the diagram.
      This is implemented by a custom <a>Part.dragComputation</a> function.
    </p>
    <p>
      Note that the user may still zoom the whole page.
    </p>
    <p>The model data, automatically updated after each change or undo or redo:</p>
    <textarea id="mySavedModel" style="width:100%;height:150px"></textarea>
  </div>
</body>
</html>
